// Copyright 2022 The Google Research Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef THIRD_PARTY_DNN_ACCELERATOR_HLS_SRC_DESERIALIZER_H_
#define THIRD_PARTY_DNN_ACCELERATOR_HLS_SRC_DESERIALIZER_H_

#include <mc_scverify.h>

#include "src/AccelTypes.h"

template <typename T, int COUNT>
class Deserializer {
 public:
  Deserializer() {}

#pragma hls_design interface
  void CCS_BLOCK(run)(ac_channel<T> &in, ac_channel<Pack1D<T, COUNT> > &out) {
#ifndef __SYNTHESIS__
    while (in.available(1))
#endif
    {
      Pack1D<T, COUNT> data;
      for (int i = 0; i < COUNT; i++) {
        data.value[i] = in.read();
      }

      out.write(data);
    }
  }
};

template <typename T, int SIZE_A, int SIZE_B>
class VectorDeserializer {
 public:
  VectorDeserializer() {}

#pragma hls_design interface
  void CCS_BLOCK(run)(ac_channel<Pack1D<T, SIZE_A> > &in,
                      ac_channel<Pack1D<T, SIZE_B> > &out) {
#ifndef __SYNTHESIS__
    while (in.available(1))
#endif
    {
      Pack1D<T, SIZE_B> fullData;
      for (int chunk = 0; chunk < SIZE_B / SIZE_A; chunk++) {
        Pack1D<T, SIZE_A> partialData = in.read();

#pragma hls_unroll yes
        for (int i = 0; i < SIZE_A; i++) {
          fullData.value[chunk * SIZE_A + i] = partialData.value[i];
        }
      }

      out.write(fullData);
    }
  }
};

template <typename T, int COUNT>
class Serializer {
 public:
  Serializer() {}

#pragma hls_design interface
  void CCS_BLOCK(run)(ac_channel<Pack1D<T, COUNT> > &in, ac_channel<T> &out) {
#ifndef __SYNTHESIS__
    while (in.available(1))
#endif
    {
      Pack1D<T, COUNT> data = in.read();
      for (int i = 0; i < COUNT; i++) {
        out.write(data.value[i]);
      }
    }
  }
};

#endif  // THIRD_PARTY_DNN_ACCELERATOR_HLS_SRC_DESERIALIZER_H_
